import React from 'react'
import { findDOMNode } from 'react-dom';
import _ from 'underscore'
import $ from 'jquery'
import Card from 'lib/components/card.jsx'
import CardSpec from '../common/CardSpec.jsx'
import format from 'lib/util/format'

function countTicksArray(min,max,m){
  m = m || 1;
  var extent = [min,max],
  span = extent[1] - extent[0],
  step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)),
  err = m / span * step;
  if(err <= 0.15){
    step *= 10;
  }else if(err <= 0.35){
    step *= 5;
  }else if(err <= 0.75){
    step *= 2;
  }
  extent[0] = Math.ceil(extent[0] / step) * step;
  extent[1] = Math.ceil(extent[1] / step) * step + step * 0.5;
  extent[2] = step;
  var list = _.range.apply(_,extent)
  return {
    list:list,
    step:step,
    min:list[0],
    max:list[list.length-1]
  };
}

export default class ActivityTrace extends React.Component{
  constructor(props){
    super(props);
    this.handleMouseMove = this.handleMouseMove.bind(this);
    this.handleMouseEnter = this.handleMouseEnter.bind(this);
    this.handleMouseLeave = this.handleMouseLeave.bind(this);
    this.state = {
      active:false,
      lineX:-10000,
      x:-10000,
      y:-10000,
      width:null,
      target:null
    }
  }
  componentDidUpdate(){
    var $swim = $(findDOMNode(this)).find('.swim-graph')
    $('.swim-graph-num-line').height($swim.height()-18)
  }
  handleMouseEnter(e){
    this.setState({
      active:true
    })
  }
  handleMouseMove(e){
    var $parent = $(e.currentTarget)
    , offset = $parent.offset()
    , w = $parent.width()
    , h = $parent.height()
    , $target = $(e.target)
    , $serie = ($target.is('.swim-graph-series')&&$target) || $target.parents('.swim-graph-series')
    var state = {
      lineX:Math.max(e.pageX - offset.left,w*0.2),
      x:e.pageX - offset.left + 5,
      y:e.pageY - offset.top + 15,
      width:w
    }
    if(e.pageX - offset.left > w*0.2){
      state.active = true;
    }else{
      state.active = false
    }
    if(state.x > w - 290){
      state.x = state.x - 330
    }
    if(state.y > h - 200){
      state.y = state.y - 230
    }
    if($serie.length){
      state.target = $serie.index() - 1
    }else{
      state.target = null
    }
    this.setState(state)
  }
  handleMouseLeave(e){
    this.setState({
      active:false
    })
  }
  renderLoading(){
    return (
      <div className="widget-content">
      <DefaultLoadingElement />
      </div>
      )
  }
  renderTooltip(detail){
    var duration = detail.endTime - detail.startTime
    , ticks = countTicksArray(0,duration,10)
    , w = this.state.width
    var currentTime = Math.round(
      Math.min(
        ticks.max,
        (this.state.lineX - w*0.2)*(ticks.max/(w*0.8))
        )
      )
    var currentMemory = detail.vitals.memory&&_(detail.vitals.memory).find(function(i){
      return i.startTime <= currentTime &&i.duration + i.startTime >= currentTime
    })
    var networkCount = _.filter(detail.traces,function(trace){
      return trace.type === 'network'
      && (trace.startTime - detail.startTime <= currentTime)
      && (trace.endTime - detail.startTime >= currentTime)
    }).length
    var currentTrace = this.state.target!==null&&detail.traces[this.state.target]
    var detailTip = null
    if(currentTrace){
      if(currentTrace.type==='network'){
        detailTip = (
          <ul>
          <li key="name" className="text-overflow">{currentTrace.name}</li>
          <li key="d"><em>{format.integer(currentTrace.endTime - currentTrace.startTime)+'ms'}</em>耗时：</li>
          <li><em>{(currentTrace.info.bytes_received||'0') +'bytes'}</em>接收数据量：</li>
          <li><em>{currentTrace.info.status_code}</em>HTTP返回码：</li>
          <li><em>{currentTrace.thread}</em>线程：</li>
          {
            currentTrace.path
              ? (
                <li style={{height:'42px'}}><em style={{
                  position:'absolute',
                  maxWidth:'255px',
                  right:'6px'
                }}>{currentTrace.path}</em>路径：</li>
              ) : null
          }
          </ul>
        )
      }else if(currentTrace.type==='trace'){
        detailTip = (
          <ul>
          <li key="name" className="text-overflow">{currentTrace.name}</li>
          <li key="d"><em>{format.integer(currentTrace.endTime - currentTrace.startTime)+'ms'}</em>耗时：</li>
          <li><em>{format.integer(currentTrace.startTime - detail.startTime)+'ms'}</em>起始时间：</li>
          <li><em>{currentTrace.method}</em>线程：</li>
          </ul>
        )
      }
    }
    return (
      <div>
        <div className="swim-mouse-line mouseover" style={{left: this.state.lineX + 2 }}></div>
        <div className="swim-mouse-tips mouseover" style={{
          left: this.state.x,
          top: this.state.y + ((currentTrace.type === 'network' && currentTrace.path) ? -40 : 30),
          display:this.state.active?'block':'none'
        }}>
        <div>
        <strong>{format.integer(currentTime)+'ms'} <br />时间</strong>
        {currentMemory?(<strong>{format.numberic(currentMemory.count)+'MB'}<br />内存</strong>):null}
        <strong>{networkCount+'次'}<br />网络</strong>
        </div>
        {detailTip}
        </div>
      </div>
    )
  }
  renderAxis(detail){
    var duration = detail.endTime - detail.startTime
    , ticks = countTicksArray(0,duration,10)
    return (
      <div className="swim-graph-bar">
      {
        ticks.list.map(function(tick,ind,arr){
          return (
            <div key={ind} className="swim-graph-num" style={{left: (ind/(arr.length - 1)*100)+'%'}}>
            <div className="swim-graph-num-label">{tick}</div>
            <div className="swim-graph-num-line"></div>
            </div>
            )
        })
      }
      </div>
    )
  }
  renderVitals(vitals,detail){
    var totalDuration = detail.endTime - detail.startTime
    if(!(vitals.cpu||vitals.memory)){
      return null
    }
    return (
      <div className="swim-graph-group index">
      <h4>指标</h4>
      {
        vitals.cpu?
        (
          <div className="swim-graph-series">
          <div className="swim-graph-series-label">
          <div className="swim-graph-series-label-data">
          平均
          <i>
          {
            format.rate(_.chain(vitals.cpu).pluck('count').reduce(function(v1,v2){
              return v1+v2
            },0).value()/vitals.cpu.length)
          }
          </i>
          </div>
          <span>CPU</span>
          </div>
          <div className="swim-graph-series-data">
          {
            vitals.cpu.map(function(c, i){
              return (
                <div key={i} className="points"
                style={{
                  left:((c.startTime)*100/totalDuration)+'%',
                  width:((c.duration)*100/totalDuration)+'%',
                  height:(c.rate*100)+'%'
                }}
                />
                )
            })
          }
          </div>
          </div>
          )
        :null
      }
      {
        vitals.memory?
        (
          <div className="swim-graph-series">
          <div className="swim-graph-series-label">
          <div className="swim-graph-series-label-data">
          平均
          <i>
          {
            format.numberic(_.chain(vitals.memory).pluck('count').reduce(function(v1,v2){
              return v1+v2
            },0).value()/vitals.memory.length)+'MB'
          }
          </i>
          </div>
          <span>Memory</span>
          </div>
          <div className="swim-graph-series-data">
          {
            vitals.memory.map(function(c, i){
              return (
                <div key={i} className="points"
                style={{
                  left:((c.startTime)*100/totalDuration)+'%',
                  width:((c.duration)*100/totalDuration)+'%',
                  height:(c.rate*100)+'%'
                }}
                />
                )
            })
          }
          </div>
          </div>
          )
        :null
      }
      </div>
    )
  }
  renderTrace(trace,detail,index){
    var color = (trace.type === 'trace'?'#66c5f0':'#eda75e')
    , styleObj = {};
    if(trace.type==='network'&&trace.thread==='main'){
      styleObj.fontWeight = 'bold'
    }
    if(trace.type==='trace'&&trace.method==='main'){
      styleObj.fontWeight = 'bold'
    }
    return (
      <div key={index} className="swim-graph-series">
        <div className="swim-graph-series-label" style={{
          paddingLeft:trace.lvl*10
        }}>
          <span className="cut" style={styleObj}>{trace.name}</span>
        </div>
        <div className="swim-graph-series-data">
          <div className="traces-point"
          style={{
            backgroundColor:color,
            left:((trace.startTime - detail.startTime)*100/(detail.endTime - detail.startTime))+'%',
            width:((trace.endTime - trace.startTime)*100/(detail.endTime - detail.startTime))+'%'
          }}>
          </div>
        </div>
      </div>
    )
  }
  render(){
    var detail = this.props.trace.traceDetail
      , trace = this.props.trace;
    return (
      <div className="widget-content">
        <div className="pure-g">
          <div className="pure-u-1">
            <div className="box">
              <Card>
                <table className="text-detail">
                  <tbody>
                    <tr>
                      <th>耗时：</th>
                      <td>{format.integer(trace.executeTime)+'ms'}</td>
                      <th>记录时间：</th>
                      <td>{format.stampToTime(trace.timestamp) + ' - ' + format.duration(trace.timestamp)}</td>
                      <th>操作系统：</th>
                      <td>{trace.osName + ' ' + trace.osVersionName}</td>
                    </tr>
                  {detail.deviceInfo.ext?(
                    <tr>
                      <th>设备：</th>
                      <td>{detail.deviceInfo.brand + ' ' + detail.deviceInfo.modelName}</td>
                      <th>地理信息：</th>
                      <td>{detail.deviceInfo.ext.location}</td>
                      <th>联网方式：</th>
                      <td>{detail.deviceInfo.ext.carrier}</td>
                    </tr>
                    ):null}
                  {detail.deviceInfo.ext?(
                    <tr>
                      <th>剩余电量：</th>
                      <td>{detail.deviceInfo.ext.power + '%'}</td>
                      <th>UI朝向：</th>
                      <td>{detail.deviceInfo.ext.ui_orientation==='portrait'?'竖屏':'横屏'}</td>
                      {
                        detail.deviceInfo.ext.rooted?(
                          [
                            <th key={0}>是否Root：</th>,
                            <td key={1}>{detail.deviceInfo.ext.rooted==='1'?'是':'否'}</td>
                          ]
                        ):null
                      }
                    </tr>
                    ):null}
                  </tbody>
                </table>
              </Card>
            </div>
          </div>
        </div>
        <div className="pure-g">
          <div className="pure-u-1">
          {
            detail.otherApp?(
              <div className="box">
                <CardSpec title="后台App" useToggle={true}>
                  <table className="table table-striped">
                    <tbody>
                      <tr>
                        <th>PID</th>
                        <th>名称</th>
                        <th>程序包名</th>
                        <th>内存占用</th>
                      </tr>
                      {
                        detail.otherApp.map(function(app,i){
                          return (
                            <tr key={i}>
                              <td>{app.pid}</td>
                              <td>{app.name}</td>
                              <td>
                              {
                                app.packages.map(function(p,index){
                                  var tu = [<br />,p]
                                  if(!index){
                                    tu.shift()
                                  }
                                  return tu
                                })
                              }
                              </td>
                              <td>{format.dataSize(app.mem)}</td>
                            </tr>
                            )
                        })
                      }
                    </tbody>
                  </table>
                </CardSpec>
              </div>
            ):null
          }
          </div>
        </div>
        <div className="pure-g">
          <div className="pure-u-1">
            <div className="box">
              <Card>
                <div className="swim-graph"
                  onMouseMove={this.handleMouseMove}
                  onMouseEnter={this.handleMouseEnter}
                  onMouseLeave={this.handleMouseLeave}
                >
                  {this.renderTooltip(detail)}
                  {this.renderAxis(detail)}
                  <div className="swim-graph-container">

                    {this.renderVitals(detail.vitals,detail)}
                    <div className="swim-graph-group">
                    <h4>Traces</h4>
                    {
                      detail.traces.map(function(innerTrace, i){
                        return this.renderTrace(innerTrace,detail, i)
                      },this)
                    }
                    </div>
                  </div>
                </div>
              </Card>
            </div>
          </div>
        </div>
      </div>
    )
  }
}
